home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2005 October
/
PCWOCT05.iso
/
Software
/
Resources
/
CutePDF 2.3
/
converter.exe
/
GNUGS
/
PDF_FONT.PS
< prev
next >
Wrap
Text File
|
2002-04-17
|
39KB
|
1,224 lines
% Copyright (C) 1994-2002 artofcode LLC. All rights reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
% $Id: pdf_font.ps,v 1.23.2.6 2002/04/16 06:11:29 giles Exp $
% pdf_font.ps
% PDF font operations.
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
GS_PDF_ProcSet begin
pdfdict begin
% We cache the PostScript font in an additional element of the
% font resource dictionary, called PSFont.
% ---------------- Encodings ---------------- %
% Apply a list of differences to an Encoding.
% Note that the differences may cause the array to grow.
/updateencoding { % <encoding> <differences> updateencoding <enc'>
% Calculate the length of the result.
exch 0 2 index {
dup type /nametype ne { exch pop } { pop 1 add } ifelse
} forall
1 index length .max array dup 0 4 -1 roll putinterval
exch 0 exch {
% Stack: enc' code element
dup type /nametype ne
{ exch pop }
{ 3 copy put pop 1 add }
ifelse
} forall pop
} bdef
% Get the Encoding for a font.
/getencoding % <base-encoding> <font-resource> getencoding <enc>
{ /Encoding knownoget
{ dup type /nametype eq
{
% The published PDF specification says the Encoding name
% "must be" one of the 3 predefined Encodings, implying
% that an error should occur if it isn't. However, Acrobat
% Reader simply ignores unknown names, and since there are
% some buggy applications that rely on this, we do the same.
dup dup dup /MacRomanEncoding eq
exch /MacExpertEncoding eq or
exch /WinAnsiEncoding eq or
{ exch pop findencoding
}
{ pop
}
ifelse
}
{ dup /BaseEncoding knownoget
{ findencoding 3 -1 roll pop exch
}
if
/Differences knownoget { updateencoding } if
}
ifelse
}
if
} bdef
% Rename a font with a generated name.
/renamefont { % <fontdict> renamefont <font'>
dup /FontName 2 copy get genfontname dup 5 1 roll put definefont
} bind def
% Adjust a font according to the Encoding and Widths in the font resource.
/adjustfont { % <font-resource> <font> adjustfont <font'>
getfontencoding
getfontmetrics 4 -1 roll pop .updatefont { renamefont } if
} bind def
% Get the (possibly modified) encoding of a font.
/getfontencoding { % <font-resource> <font> getfontencoding
% <font-resource> <font> <Encoding|null>
1 index /Encoding known {
dup /Encoding .knownget { 2 index getencoding } { null } ifelse
} {
null
} ifelse
} bdef
/find_in_diff % <Differences> <index> find_in_diff <bool>
{ false exch 0 4 3 roll
{ dup type /nametype ne { exch pop } { pop 1 add } ifelse
2 copy eq {
pop pop pop true 0 0 exit
} if
} forall
pop pop
} bdef
% Get the metrics of a font, if specified.
/getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics
% <font-resource> <font> <Encoding|null>
% <Metrics|null>
2 index /Widths known {
dup null eq { pop dup /Encoding get } if
4 dict begin
/Encoding exch def
/Metrics Encoding length dict def
exch
dup /Widths oget /Widths exch def
% Stack: font font-res
% Note that widths are always based on a 1000-unit
% character space, but the FontMatrix may specify
% some other scale factor. Compensate for this here,
% by scaling the Widths if necessary.
0.001 2 index /FontMatrix get 0 get div
% Stack: font font-res mscale
1 index /FirstChar oget dup 1 4 index /LastChar oget
{ % Stack: font font-res mscale first-char index
Encoding 1 index get
Widths 2 index 4 index sub oget
% Stack: font font-res mscale first-char index charname width
4 index mul
% The following 'loop' is only context for 'exit'.
{
% Work around a bug in pdfTeX, which can generate Encoding
% vectors containing nulls :
1 index null eq { exit } if
% There is a hack here to deal with encodings where the
% same character appears more than once, because the Metrics
% dictionary works by character name, not by character code.
% We prefer to take (1) non-zero width, and (2) width for
% the character code which appears in Differences.
Metrics 2 index .knownget not { 0 } if 0 ne {
5 index /Encoding knownoget not { exit } if
dup type /dicttype ne { pop exit } if
/Differences knownoget not { exit } if
3 index //find_in_diff exec not { exit } if
} if
2 copy Metrics 3 1 roll put
exit
} loop
pop pop pop
}
for pop
% Now fill in the MissingWidth for any encoded characters
% that aren't in Metrics already. Note that built-in
% fonts may have Widths/FirstChar/LastChar but no
% FontDescriptor, so we must check for this.
% Stack: font font-res mscale
1 index /FontDescriptor knownoget {
Metrics exch
/MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
Encoding {
% Stack: font font-res mscale missing-width metrics charname
% Work around the abovementioned pdfTeX bug.
dup null ne {
2 copy known not { 2 copy 4 index put } if pop
} {
pop
} ifelse
} forall pop pop pop
} {
pop
} ifelse
exch Encoding Metrics end
} {
null
} ifelse
} bdef
currentdict /find_in_diff undef
% ---------------- Descriptors ---------------- %
% Partial descriptors for the 14 built-in fonts. Note that
% from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
% object has undergone a subtle change in its meaning which has serious
% consequences for searching with Acrobat:
% In PDF 1.1, the flag meant: Font has StandardEncoding
% In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
/standardfontdescriptors mark
/Courier mark /Flags 16#23 .dicttomark
/Courier-Oblique 1 index
/Courier-Bold 1 index
/Courier-BoldOblique 1 index
/Helvetica mark /Flags 16#20 .dicttomark
/Helvetica-Oblique 1 index
/Helvetica-Bold 1 index
/Helvetica-BoldOblique 1 index
/Times-Roman mark /Flags 16#22 .dicttomark
/Times-Bold 1 index
/Times-Italic mark /Flags 16#62 .dicttomark
/Times-BoldItalic 1 index
/Symbol mark /Flags 16#4 .dicttomark
/ZapfDingbats 1 index
.dicttomark readonly def
% ---------------- Utilities ---------------- %
/.glyphpath { % <glyphname> <boolean> .glyphpath -
% another glyphpath written in addxchar.ps does not work here...
currentfont 3 1 roll exch
currentfont dup length dict begin
{ 1 index /Encoding eq { pop [ 3 -1 roll ] def } { def } ifelse } forall
currentdict end /.glyphpathfont exch definefont
setfont <00> exch charpath setfont
} bdef
/makeboldfont { % <basefont> <strokewidth> makeboldfont <boldfont>
10 dict begin
/strokewidth exch def
/basefont exch def
/FontMatrix matrix def
%/FontName basefont /FontName get def
/FontName /.boldfont def
/FontType 3 def
/Encoding basefont /Encoding get def
/FontBBox [ basefont /FontBBox get cvx exec
4 2 roll basefont /FontMatrix get transform
4 2 roll basefont /FontMatrix get transform
] def
/BuildGlyph {
gsave
exch begin
basefont setfont
strokewidth setlinewidth
1 setlinejoin
newpath
0 0 moveto dup false .glyphpath stroke
0 0 moveto glyphshow
currentpoint setcharwidth
end
grestore
} bind def
currentdict
end
dup /FontName get exch definefont
} bind def
% Fabricate a font name by adding ?'s on the end.
/genfontname % <name> genfontname <name>
{ dup length string cvs
{ (?) concatstrings
dup cvn FontDirectory exch known not { cvn exit } if
}
loop
} bdef
% Find a font, and adjust its encoding if necessary.
/.pdfdfndict mark
/defaultfontname /Helvetica
.dicttomark readonly def
/pdffindfont { % <font-resource> <fontname> pdffindfont <font>
% If the font isn't available, synthesize one based on
% its descriptor.
dup /Font resourcestatus {
pop pop findfont
} {
1 index /FontDescriptor knownoget {
% Stack: font-res fontname fontdesc
dup /Flags oget
dup 16#40 and -6 bitshift % 1, oblique/italic
1 index 16#40000 and -17 bitshift add % 2, bold
exch 16#2 and 2 bitshift add % 8, serif
% We should look at the fixed flag, too.
% Stack: font-res fontname fontdesc properties
1 index /FontName oget exch
% Analyzes font name and extract "Narrow" property
% which is not described by the FontDescriptor Flags.
0 2 index .fontnameproperties 4 and or
% Rebind the default font name to Helvetica so that
% fonts with no properties are handled correctly.
//.pdfdfndict begin .substitutefontname end
% Stack: font-res fontname fontdesc substname|null
Fontmap 1 index known not {
% No available good substitution, use the standard one.
pop 1 index .substitutefont
} if
QUIET not {
(Substituting font ) print dup =only
( for ) print 2 index =only (.) = flush
} if
3 -1 roll pop findfont
% Stack: font-res fontdesc font
% If this is a small-caps font, replace the CharString
% entries for a..z.
exch /Flags oget 16#20000 and 0 ne {
true .copyfontdict
dup /CharStrings 2 copy get dup length dict .copydict
4 index /FirstChar get 97 .max
5 index /LastChar get 122 .min 1 exch {
% Stack: font-res font' font' /CharStrings charstrings code
% Note that this only remaps a-z, not accented characters.
5 index /Widths oget 1 index 7 index /FirstChar get sub oget
1 string dup 0 5 -1 roll put
% Stack: font-res font' font' /CharStrings charstrings code
% width (x)
2 index exch dup cvn exch
dup 0 2 copy get 32 sub put 4 -1 roll {
% Stack: operand (X) width
0 setcharwidth exch pop
currentfont /FontMatrix get matrix invertmatrix concat
0.7 dup scale 0 0 moveto show
} /exec cvx 4 packedarray cvx put
} for put
renamefont
} if
} {
% No descriptor available, use the default algorithm.
findfont
} ifelse
} ifelse adjustfont
} bdef
/findpdffont { % <font-resource> <fontname> findpdffont <font>
{} 3 1 roll % proc fnres fnname
[
[ (,Bold) { .03 makeboldfont } ]
[ (,BoldItalic) { .03 makeboldfont [ 1 0 .3 1 0 0 ] makefont } bind ]
[ (,Italic) { [ 1 0 .3 1 0 0 ] makefont } bind ]
] {
1 index dup length string cvs
1 index 0 get tailmatch { % proc fnres fnname []
3 -1 roll pop exch 1 get % proc fnres pre-fnname proc
4 -1 roll pop 3 1 roll % proc fnres pre-fnname
exit
} { pop pop } ifelse % proc fnres fnname
} forall
pdffindfont exch exec
} bdef
% ---------------- Type 1 fonts ---------------- %
/buildType1 % <Type1-font-resource> buildType1 <font>
{ dup /BaseFont get pdffindfont
} bdef
% The state dictionary for the embedded Type 1 font reading procedure
% has the following keys and values:
% data - stream (filter)
% buffer, buffer2 - string
% hexify - procedure to convert buffer to hex if needed
% leftstr - string containing (non-negative) integer
% sectionstr - string containing a character 0 .. 3
% stream - (stream) dictionary
% proc - procedure of the form {-dict- type1read}
% pfbhdr - string containing 16#80 if PFB, 0 otherwise
% When the procedure is executing, this dictionary is current.
% leftstr and sectionstr are strings so that we can change their values
% reliably in case the font executes a restore!
% We also have to do something special about embedded fonts that
% execute definefont more than once -- that is the function of topFontDict.
% Read an embedded Type 1 font.
/readfontfilter { % <proc> readfontfilter <filter>
0 () /SubFileDecode filter
} bdef
/readtype1dict 5 dict dup begin
/definefont {
dup topFontDict eq topFontDict null eq or {
dup wcheck not { dup length dict copy } if
exch pop savedFontName exch
} if
//systemdict /definefont get exec
} bdef
/eexec {
% Assume the font dictionary is directly below the file on the stack
count 0 gt { /topFontDict 2 index cvlit store } if
55665 /eexecDecode filter
//systemdict begin readtype1dictcopy begin cvx stopped
currentdict readtype1dictcopy eq { end } if
currentdict //systemdict eq { end } if
{ stop } if
} bdef
end readonly def
/readtype1 { % <font-resource> <stream-dict> readtype1 <font>
% Read the definition, using a procedure-based filter
% that turns binary/hex conversion on and off
% at the right times.
1 index exch
PDFfile fileposition 3 1 roll
11 dict begin
/leftstr ( ) 10 string copy def
dup /Length1 oget leftstr cvs pop
/sectionstr <00> 1 string copy def
/pfbhdr <00> 1 string copy def
/stream 1 index def
true resolvestream /data exch def
/buffer 1000 string def % arbitrary
/buffer2 buffer length 2.1 div cvi 1 sub string def
/hexify /buf2hex load def
currentdict end
/type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
readfontfilter
% Some buggy embedded fonts leave extra junk on the stack,
% so we have to make a closure that records the stack depth
% in a fail-safe way.
//systemdict begin
% The PDF specification is somewhat muddy about whether
% an embedded font's name is supposed to be the BaseFont
% from the Font object or the FontName from the descriptor.
% Acrobat Distiller requires the former. Save away the
% name so we can substitute it at definefont time.
//readtype1dict dup length 3 add dict copy begin
1 index /BaseFont oget /savedFontName exch def
/topFontDict null def
/readtype1dictcopy currentdict def
{ run } aload pop count 1 sub 2 packedarray cvx exec
end end
count exch sub { pop } repeat
PDFfile 3 -1 roll setfileposition
/BaseFont oget findfont
adjustfont
} bdef
% Execute the appropriate reading procedure.
/type1read % <dict> type1read <string>
{ begin leftstr cvi
{ type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
( ) leftstr copy cvs pop end
} bdef
% Read the next block of data into the buffer.
/type1readdata % <left> <buffer> type1readdata <substring> <left'>
{ 0 2 index 2 index length .min getinterval
% Adobe requires readstring to signal an error if given
% an empty string. Work around this nonsense here.
dup length 0 ne { data exch readstring pop } if
dup length 3 -1 roll exch sub
DEBUG
{ dup =only ( read ) print
1 index length =only (: ) print
1 index == flush
} if
} bdef
% Read the initial byte to see if we need to skip a 6 byte PFB header
/type1read0 { % <left> type1read0 <string> <left'>
sectionstr 0 1 put % either way we go to the next stage
pfbhdr type1readdata
1 index 0 get 16#80 eq {
(\n **** Warning: Embedded Type1 font in PFB format is not valid PDF.)
pdfformaterror
DEBUG { (skipping PFB header) = flush } if
exch pop buffer 0 5 getinterval type1readdata exch
dup 4 get 256 mul 1 index 3 get add 256 mul
1 index 2 get add 256 mul 1 index 1 get add
DEBUG { (PFB segment length = ) print dup = } if
exch pop % discard the string keeping the PFB segment length
2 copy ne {
(\n **** Warning: Type 1 PFB segment length and Length 1 value do not match.)
pdfformaterror
exch % keep the PFB length instead
} if
pop
buffer type1readdata % go ahead and read a block
}
if % if not PFB, return pfbhdr string (first char of file, usually %).
} bdef
% Read the next block of the initial text portion.
/type1read1 { % <left> type1read1 <string> <left'>
DEBUG { (read1 ) print } if
dup 0 eq {
pop sectionstr 0 2 put
stream /Length2 oget
% Determine whether to hexify data for eexec.
dup 8 lt {
type1read2 % Hexify.
} {
DEBUG { (read2 ) print } if
pfbhdr 0 get 16#80 eq {
% eat 6 more bytes of PFB junk before proceeding
DEBUG { (skipping PFB header in segment 2) = flush } if
buffer 0 6 getinterval type1readdata exch
dup 5 get 256 mul 1 index 4 get add 256 mul
1 index 3 get add 256 mul 1 index 2 get add
DEBUG { (PFB segment length = ) print dup = } if
exch pop % discard the string keeping the PFB segment length
2 copy ne {
(\n **** Warning: Type 1 PFB segment length and Length 2 value do not match.)
pdfformaterror
dup =
exch % keep the PFB length instead
} if
pop
} if
buffer2 type1readdata exch
% The check doesn't have to be 100% accurate:
% hexifying is always OK.
dup 0 8 getinterval 0 exch { or } forall
128 ge {
/hexify { } store
/buffer2 buffer def % We don't need an intermediate buffer.
} if hexify exch
} ifelse
} {
buffer type1readdata
} ifelse
} bdef
% Convert a string from binary to hex for eexec.
% Free variables: buffer.
/buf2hex { % <string> buf2hex <hexstring>
buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
buffer (>) search pop exch pop exch pop
} bdef
% Read the next block of the encrypted portion.
/type1trailer
(0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
cleartomark\n)
readonly def
/type1read2 { % <left> type1read2 <string> <left'>
DEBUG { (read2 ) print } if
dup 0 eq
{ pop sectionstr 0 3 put
stream /Length3 oget
dup 0 eq
{ DEBUG { (trailer ) print } if
type1trailer exch
}
{
pfbhdr 0 get 16#80 eq {
% eat 6 more bytes of PFB junk before proceeding
DEBUG { (skipping PFB header in segment 3) = flush } if
buffer 0 6 getinterval type1readdata exch
dup 5 get 256 mul 1 index 4 get add 256 mul
1 index 3 get add 256 mul 1 index 2 get add
DEBUG { (PFB segment length = ) print dup = } if
exch pop % discard the string keeping the PFB segment length
2 copy ne {
(\n **** Warning: Type 1 PFB segment length and Length 3 value do not match.)
pdfformaterror
exch % keep the PFB length instead
} if
pop
(\n) pdfformaterror
} if
type1read3
}
ifelse
}
{ buffer2 type1readdata exch hexify exch
}
ifelse
} bdef
% Read the next block of the final text portion.
% When finished, this procedure returns an empty string.
/type1read3 % <left> type1read3 <string> <left'>
{ DEBUG { (read3 ) print } if
buffer type1readdata
} bdef
% ---------------- Type 3 fonts ---------------- %
/.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
/buildType3 { % <Type3-font-resource> buildType3 <font>
8 dict begin
/FontType 3 def
/Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
/FontBBox 1 index /FontBBox get cvx def
/FontMatrix 1 index /FontMatrix oget def
/CharProcs 1 index /CharProcs oget def
1 index /Widths knownoget {
/Widths exch def
/FirstChar 1 index /FirstChar oget def
/LastChar 1 index /LastChar oget def
} if
/FontName 1 index /Name get genfontname def
/Encoding .notdefEncoding 2 index getencoding def
% We have to define BuildChar rather than BuildGlyph:
% there is no PDF equivalent of glyphshow, and we need
% the character code to access the Widths.
/BuildChar {
% Stack: font charcode
1 index begin 3 dict begin
/Font 3 -1 roll def /CharCode 1 index def
% Make unknown characters map to /.notdef
Encoding exch get dup CharProcs exch known
{ CharProcs exch oget }
{ pop CharProcs /.notdef oget }
ifelse
PDFfile fileposition exch
false resolvestream
% Stack: filepos stream
% Don't let setgcolor set the color inside the BuildGlyph
% procedure, because this causes an /undefined error.
q null /FillColor gput null /StrokeColor gput
Font /Resources get exch pdfopdict .pdfruncontext
Q
PDFfile exch setfileposition
end end
} bdef
FontName currentdict end definefont exch pop
} bdef
/.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'>
/Widths where {
begin
CharCode FirstChar ge CharCode LastChar le and {
exch pop Widths CharCode FirstChar sub get exch
} if end
} if
} bdef
% ---------------- TrueType fonts ---------------- %
/TTfonts mark
/Arial /Helvetica
/Arial,Italic /Helvetica-Oblique
/Arial,Bold /Helvetica-Bold
/Arial,BoldItalic /Helvetica-BoldOblique
/CourierNew /Courier
/CourierNew,Bold /Courier-Bold
/TimesNewRoman /Times-Roman
/TimesNewRoman,Italic /Times-Italic
/TimesNewRoman,Bold /Times-Bold
/TimesNewRoman,BoldItalic /Times-BoldItalic
%
/ArialBlack,Italic /Arial-BlackItalic
/ArialNarrow,Bold /ArialNarrow-Bold
/ArialNarrow,BoldItalic /ArialNarrow-BoldItalic
/ArialNarrow,Italic /ArialNarrow-Italic
/BookAntiqua,Bold /BookAntiqua-Bold
/BookAntiqua,BoldItalic /BookAntiqua-BoldItalic
/BookAntiqua,Italic /BookAntiqua-Italic
/BookmanOldStyle,Bold /BookmanOldStyle-Bold
/BookmanOldStyle,BoldItalic /BookmanOldStyle-BoldItalic
/BookmanOldStyle,Italic /BookmanOldStyle-Italic
/CenturyGothic,Bold /CenturyGothic-Bold
/CenturyGothic,BoldItalic /CenturyGothic-BoldItalic
/CenturyGothic,Italic /CenturyGothic-Italic
/ComicSansMS,Bold /ComicSansMS-Bold
/CourierNew,Bold /CourierNewPS-BoldMT
/CourierNew,BoldItalic /CourierNewPS-BoldItalicMT
/CourierNew,Italic /CourierNewPS-ItalicMT
/FranklinGothicMedium,Italic /FranklinGothic-MediumItalic
/Garamond,Bold /Garamond-Bold
/Garamond,Italic /Garamond-Italic
/Georgia,Bold /Georgia-Bold
/Georgia,BoldItalic /Georgia-BoldItalic
/Georgia,Italic /Georgia-Italic
/Tahoma,Bold /Tahoma-Bold
/TrebuchetMS,Bold /TrebuchetMS-Bold
/TrebuchetMS,BoldItalic /Trebuchet-BoldItalic
/TrebuchetMS,Italic /TrebuchetMS-Italic
/Verdana,Bold /Verdana-Bold
/Verdana,BoldItalic /Verdana-BoldItalic
/Verdana,Italic /Verdana-Italic
.dicttomark readonly def
/buildTrueType { % <TrueType-font-resource> buildTrueType <font>
dup /BaseFont get
dup TTfonts exch .knownget {
exch pop
% Hack required by the PDF specification: if the
% font resource has Subtype = /TrueType but the actual
% (installed) font is not a TrueType font, ignore the
% Encoding in the font resource. However, all current
% versions of Acrobat Reader have the 14 base TrueType
% fonts built in, so this produces incorrect output for
% badly designed PDF files that specify these file names
% with /Subtype = /TrueType but no embedded definition.
% Compensate for this by removing the /Subtype key when
% looking up the font.
exch dup length dict copy dup /Subtype null put exch
} if
pdffindfont % findfont for PDF
% disable the auto-bold and auto-italic since it sometimes applies
% so an already bold or italic substitute font
%findpdffont % findfont and auto-bold and/or auto-italic font for PDF
} bdef
% Read an embedded TrueType font.
/readtruetype { % <font-resource> <stream-dict> readtruetype <font>
% This is much simpler than readtype1, because we don't
% have to deal with the tripartite .PFB format.
1 index exch
PDFfile fileposition 3 1 roll
true resolvestream readfontfilter
% Stack: filepos fontres stream
1 index /Subtype get /CIDFontType2 eq {
.loadttcidfont
% Stack: filepos fontres cidfont
1 index /CIDToGIDMap knownoget {
dup /Identity eq {
pop
} {
true resolvestream
% The following doesn't work for CIDToGIDMaps with more
% than 32K-1 entries. We'll fix it later if necessary.
% Stack: filepos fontres font mapstream
dup 2 index /CIDCount oget 2 mul string readstring pop exch closefile
exch dup length 5 add dict .copydict
dup /FID undef
dup /CIDMap 4 -1 roll put
dup /CIDFontName get exch /CIDFont defineresource
} ifelse
} if
} {
null 2 index getencoding .loadpdfttfont
} ifelse
exch pop
PDFfile 3 -1 roll setfileposition
% Ignore both the Encoding and the Widths.
exch pop
} bdef
% ---------------- Type 0 fonts ---------------- %
% Predefine the known CMaps, but only create them on demand.
/knownCMaps mark
/Identity-H { /Identity-H 0 makeIdentityCMap }
/Identity-V { /Identity-V 1 makeIdentityCMap }
.dicttomark def
/makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap -
.currentglobal true .setglobal 3 1 roll
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/WMode exch def
/CMapName exch def
/CIDSystemInfo 3 dict dup begin
/Registry (Adobe) def
/Ordering (Identity) def
/Supplement 0 def
end def
%/CMapName (see above)
/CMapVersion 1 def
/CMapType 1 def
%WMode (see above)
% The PDF documentation says that these CMaps map CIDs
% "1 to 65,536". This is a misprint for 0 to 65,535.
1 begincodespacerange
% <0001> <00ff> <0100> <ffff>
<0000> <ffff>
endcodespacerange
1 begincidrange
% <0001> <00ff> 1 <0100> <ffff> 256
<0000> <ffff> 0
endcidrange
endcmap
CMapName currentdict /CMap defineresource
knownCMaps CMapName 2 index put
end % CMap
end % CIDInit ProcSet
exch .setglobal
} bdef
/buildType0 { % <Type0-font-resource> buildType0 <font>
dup /BaseFont get % FontName
1 index /Encoding oget
dup type /nametype eq {
dup /CMap resourcestatus {
pop pop /CMap findresource
} {
knownCMaps 1 index .knownget
{ exch pop exec } { /undefined signalerror } ifelse
} ifelse
} {
PDFfile fileposition exch
dup /CMapName get exch true resolvestream cvx exec
/CMap findresource
exch PDFfile exch setfileposition
} ifelse % CMap
[
3 index /DescendantFonts oget { exec resourcefont } forall
] % subfonts
composefont
% Stack: fontres font
1 index /FontMatrix knownoget {
dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
1 index exch makefont exch /FontName get exch definefont
} {
pop
} ifelse
} if exch pop
} bdef
% ---------------- CIDFontType0/2 fonts ---------------- %
% Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
% arrays and using a (currently very inefficient) CDevProc.
% For detail, refer "PDF Reference" third edition, p. 337,
% "5.6.3 CIDFonts" and table "Entries in a CIDFont dictionary".
/.pdfDefaultDW 1000 def
/.pdfDefaultDW2 [ 880 -1000 ] def
/addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
dup length 5 add dict .copydict
dup /FID undef
dup /UniqueID undef
dup /XUID undef
% Insert the widths into the font.
% Stack: pdfresource newfont
1 index /DW .knownget {
1 index /DW 3 -1 roll put
} {
dup /DW .pdfDefaultDW put
} ifelse
1 index /W .knownget {
dup 2 index /W 3 -1 roll put
.pdfMakeInternalW 1 index /.internalW 3 -1 roll put
} if
1 index /DW2 .knownget {
1 index /DW2 3 -1 roll put
} {
dup /DW2 .pdfDefaultDW2 put
} ifelse
1 index /W2 .knownget {
dup 2 index /W2 3 -1 roll put
.pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
} if
dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
exch pop
} bdef
/.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
% convert /W or /W2 to internal expression
%
% mtx_array: original /W or /W2 array
% item_size: number of metrics values per CID
%
% for detail of the metrics list format in PDF,
% refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
%
% format of single entry in internal expression
%
% [
% [cid_begin cid_end]
% value_is_varied (bool)
% [ [values for cid_begin...]
% [values for cid_begin + 1]
% ... ]
% ]
%
7 dict
begin
/itemSize exch def
/M exch def % original /W or /W2
/Msize M length def
/Mi { M i get } def % W[i]
/Mi1 { M i 1 add get } def % W[i + 1]
/putMTXEntry <<
/arraytype {
[
[Mi Mi Mi1 length add 1 sub]
true
[
0 itemSize Mi1 length 1 sub {
[ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
} for
]
]
/i i 2 add def
}
/integertype {
[
[Mi Mi1]
false
[[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
]
/i i 3 add def
}
>> def
/i 0 def
[ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
end
} def
/.pdfMakeInternalW { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
/.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
/.pdfGetMTXByCID { % <internalMTXArray> <cid>
% .pdfGetMTXByCID
% { <MTXEntry> true | false }
% get values for given CID from internal format of /W or /W2
exch
{
{
dup 0 get {} forall % Stack: <cid> <entry> <cid_0> <cid_1>
3 index lt { pop pop false exit } if
2 index exch sub dup 0 lt { pop pop false exit } if
1 index 1 get not { pop 0 } if
exch 2 get exch get true exit
} loop
{ exit } if
} forall
dup type /arraytype eq { exch pop true } { pop false } ifelse
} def
% Apply the [D]W[2] metrics to a character before displaying.
/CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury>
% <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
% <w0x'> ... <vy'>
begin % push <font> to currentdict
% <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
5 1 roll pop pop pop pop
{
currentdict /DW .knownget not { % no DW
.pdfDefaultDW exit % replace <w0x> by defaultDW
} if
currentdict /.internalW .knownget not { % no W
exit % use already-stacked DW
} if
dup length 0 eq { % W is null array
pop % discard unusable W
exit % use already-stacked DW
} if
% W is finite array, try to get W_cid
2 index .pdfGetMTXByCID { % got W, discard DW
exch pop {} forall
exit
} if
exit
} loop
1000 div % <w0x'> (normalized W)
0 % <w0y'>
% Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
9 -2 roll pop pop % discard <w0x> <w0y>
7 2 roll % put <w0x'> <w0y'>
% Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
0 % <w1x'>
exch % put <w1x'>
% Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
{
currentdict /DW2 .knownget not { % no DW2, use defaultDW2
.pdfDefaultDW2 exit
} if
currentdict /.internalW2 .knownget not { % has DW2, no W2
exit % use already-stacked DW2
} if
dup length 0 eq { % W2 is null array
pop % discard unusable W2
exit % use already-stacked DW2
} if
2 index .pdfGetMTXByCID { % got W2_cid, discard DW2
exch pop
exit
} if
% could not get W2_cid
exit
} loop
exch pop % discard <cid>
% Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
dup length 2 eq { % this is DW2
{1000 div} forall exch
4 index 7 index add 2 div % <vx'> = (<urx> + <llx>) / 2
exch
}{ % assume W2
{1000 div} forall
} ifelse
end % recover currentdict
} def
%----------------------------------------------------------------
% <string> <match> tailmatch ==> <pre> true
% ==> <string> false
/tailmatch {
2 copy length 1 index length .min
dup 2 index length exch sub exch getinterval
1 index eq {
length 1 index length exch sub
0 exch getinterval true
} {
pop false
} ifelse
} bind def
/makeboldcidfont {
16 dict begin
/strokewidth exch def
/basecidfont exch def
/FontMatrix [ 1 0 0 1 0 0 ] def
/CIDFontName /.boldfont def
/CIDFontType 1 def
/basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
/basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
/CIDSystemInfo dup basecidfont exch get def
/FontBBox [ basecidfont /FontBBox get cvx exec
4 2 roll basecidfont /FontMatrix get transform
4 2 roll basecidfont /FontMatrix get transform
] def
/tmpstr 2 string def
/BuildGlyph {
gsave
exch begin
dup 256 idiv tmpstr exch 0 exch put
256 mod tmpstr exch 1 exch put
rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
{ basefont-V } { basefont-H } ifelse setfont
strokewidth setlinewidth
1 setlinejoin
newpath
0 0 moveto tmpstr false charpath stroke
0 0 moveto tmpstr show
currentpoint setcharwidth
end
grestore
} bind def
currentdict
end
dup /CIDFontName get exch /CIDFont defineresource
} bind def
% <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
% CIDFont-resource is not modified.
/findCIDFont {
{
dup /CIDFont resourcestatus {
pop pop /CIDFont findresource
exit
} if
dup dup length string cvs
(,Bold) tailmatch {
exch pop
cvn findCIDFont 0.03 makeboldcidfont
exit
} if
(,Italic) tailmatch {
exch pop
cvn findCIDFont
[ 1 0 0.3 1 0 0 ] makefont
exit
} if
(,BoldItalic) tailmatch {
exch pop
cvn findCIDFont 0.03 makeboldcidfont
[ 1 0 0.3 1 0 0 ] makefont
exit
} if
pop
1 index /CIDSystemInfo get begin Registry (-) Ordering end
concatstrings concatstrings
cvn
QUIET not {
(Substituting ) print dup ==only
( for ) print 1 index ==only (.\n) print
} if
exch pop
/CIDFont findresource
exit
} loop
} bdef
/buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>
dup /BaseFont get exch 1 index findCIDFont
addCIDmetrics /CIDFont defineresource
} bdef
/buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font>
dup /BaseFont get exch 1 index findCIDFont
addCIDmetrics /CIDFont defineresource
} bdef
% ---------------- Other embedded fonts ---------------- %
/fontloadprocs mark
/Type1C /readType1C cvx
/CIDFontType0C /readCIDFontType0C cvx
.dicttomark readonly def
% Read an embedded compressed font.
/readType1C { % <font-resource> <stream-dict> readType1C <font>
1 index exch
PDFfile fileposition 3 1 roll
dup true resolvestream dup readfontfilter
% Stack: pos resource streamdict stream filter
3 index /FontDescriptor oget /FontName oget
1 index FRD
closefile closefile pop
PDFfile 3 -1 roll setfileposition
/FontDescriptor oget /FontName oget findfont
adjustfont
} bdef
% Read an embedded CFF CIDFont.
/readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font>
PDFfile fileposition 3 1 roll
dup true resolvestream dup readfontfilter
% Stack: pos resource streamdict stream filter
3 index /FontDescriptor oget /FontName oget
1 index FRD
closefile closefile pop
PDFfile 3 -1 roll setfileposition
% Some broken Adobe software produces PDF files in which
% the FontName of the CFF font and the FontName in the
% FontDescriptor don't match the BaseFont in the font.
% Use the FontName, rather than the BaseFont, here.
dup /FontDescriptor oget /FontName oget /CIDFont findresource
addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
} bdef
% ---------------- Font lookup ---------------- %
/fonttypeprocs mark % <font-resource> -proc- <font>
/Type0 /buildType0 cvx
/Type1 /buildType1 cvx
/MMType1 1 index
/Type3 /buildType3 cvx
/TrueType /buildTrueType cvx
/CIDFontType0 /buildCIDType0 cvx
/CIDFontType2 /buildCIDType2 cvx
.dicttomark readonly def
/resourcefont % <font-resource> resourcefont <font>
{ dup /PSFont .knownget
{ /FID .knownget { type /fonttype eq } { false } ifelse }
{ false }
ifelse
{ /PSFont get
}
{ dup dup /FontDescriptor knownoget
{ % Stack: font-res font-res font-desc
dup /FontFile knownoget
{ exch pop readtype1 true }
{ dup /FontFile2 knownoget
{ exch pop readtruetype true }
{ /FontFile3 knownoget
{ dup /Subtype get fontloadprocs exch get exec true }
{ false }
ifelse
}
ifelse
}
ifelse
}
{ false }
ifelse
% Stack: font-res font-res false
% -or-: font-res font true
not
{ dup /Subtype get fonttypeprocs exch get exec }
if
2 copy /PSFont exch put
exch pop
}
ifelse
} bdef
drawopdict begin
/d0 {
.adjustcharwidth setcharwidth
} bdef
/d1 {
6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
} bdef
/Tf {
1 index Page /Font rget not { 1 index /invalidfont signalerror } if
resourcefont exch Tf pop
} bdef
end
end % pdfdict
end % GS_PDF_ProcSet
.setglobal